package com.starsoft.quant.analysis;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.starsoft.frame.core.orm.PageObject;
import com.starsoft.smdc.bean.SmdcMarketDaily;
import com.starsoft.smdc.bean.SmdcSecurity;
import com.starsoft.smdc.service.MarketDailyService;

@Component
public class VolatilityService {
	
	@Autowired
	MarketDailyService marketService;
	
	public double getVolatilityProfit(List<Double> profits) {
		double[] navHistory = new double[profits.size()];
		for (int i = 0; i < profits.size(); i++) {
			navHistory[i] = Math.log(profits.get(i) + 1);
		}
		StandardDeviation standardDeviation = new StandardDeviation();
		return standardDeviation.evaluate(navHistory);
	}
	
	public double getVolatility(List<SmdcMarketDaily> markets) {
		double[] navHistory = new double[markets.size()];
		for (int i = 0; i < markets.size(); i++) {
			navHistory[i] = Math.log(markets.get(i).getPercent() + 1);
		}
		StandardDeviation standardDeviation = new StandardDeviation();
		return standardDeviation.evaluate(navHistory);
	}
	
	public double getVolatilityNav(List<SmdcMarketDaily> markets) {
		double[] navList = new double[markets.size()];
		for (int i = 0; i < markets.size(); i++) {
			SmdcMarketDaily market = markets.get(i);
			navList[i] = market.getSecNav() * market.getAdjFactor();
		}
		double[] navHistory = new double[markets.size() - 1];
		for (int i = 1; i < navList.length; i++) {
			navHistory[i - 1] = Math.log(navList[i] / navList[i - 1]);
		}
		StandardDeviation standardDeviation = new StandardDeviation();
		return standardDeviation.evaluate(navHistory);
	}
	
	public double getVolatility(SmdcSecurity sec, Date beginDate, Date endDate) {
		List<SmdcMarketDaily> markets = marketService.getBetweenAnd(sec.getSecId(), beginDate, endDate);
		return getVolatility(markets);
	}
	
	@SuppressWarnings("unchecked")
	public double getVolatility(SmdcSecurity sec, int count, Date endDate) {
		PageObject po = new PageObject(1, count);
		po.setSort("tradeDate");
		po.setOrder("desc");
		marketService.pageQuery(po, sec.getSecId(), null, endDate);
		List<SmdcMarketDaily> markets = po.getRows();
		return getVolatility(markets);
	}
	
	@SuppressWarnings("unchecked")
	public double getVolatilityNav(SmdcSecurity sec, int count, Date endDate) {
		PageObject po = new PageObject(1, count);
		po.setSort("tradeDate");
		po.setOrder("desc");
		marketService.pageQuery(po, sec.getSecId(), null, endDate);
		List<SmdcMarketDaily> markets = po.getRows();
		return getVolatilityNav(markets);
	}
	
	public List<Double> rebase(List<Double> data){
		if(data==null || data.size()<1) {
			return data;
		}
		Double base = null;
		List<Double> result = new ArrayList<>();
		for(Double one : data) {
			if(base==null&&one!=null) base = one;
			if(one!=null) result.add((one/base-1)*100);
			else result.add(one);
		}
		return result;
	}
	
}
